#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string>
#include <unistd.h>
#include <netinet/in.h>
#include <time.h>
// #include <sstream>
#include <fstream>

using namespace std;

#define NTP_PORT "123"
#define PROTOCOL "ntp"
#define SEP "\\"
#define BUFFSIZE 1024

typedef struct NtpPacket{
    //这个数据结构中，mode表示数据包的模式，共有3位，其中最后一位表示包尾，为0表示包尾，为1表示包首。
    //vn表示虚拟节点号，共有3位，用于标识不同的NTP服务器。
    //li表示链路标识符，共有5位，用于标识不同的网络链路。
    unsigned char mode : 3;
    unsigned char vn : 3;
    unsigned char li : 2;

    unsigned char stratum;
    unsigned char poll;
    unsigned char precision;

    unsigned int root_delay;
    unsigned int root_dispersion;
    unsigned int reference_identifier;

    unsigned int reference_timestamp;//表示参考时间戳，表示NTP服务器收到请求包的时间戳。
    unsigned int originate_timestamp;//表示发起时间戳，表示客户端应用发出请求包的时间戳。
    unsigned int receive_timestamp;//表示接收时间戳，表示客户端应用收到响应包的时间戳。
    unsigned int transmit_timestamp;//表示发送时间戳，表示客户端应用发出响应包的时间戳。
} Packet;

typedef struct TIME{
public:
    time_t client_time;
    time_t server_time;
} TimeInfo;

class Request 
{
public:
    Request():message(""), header(""), _time({0, 0}) {}
    Request(const std::string& message) : message(message), _time({0, 0}) {}

    string wrap() 
    {
        header = "Request->";
        header += NTP_PORT;
        header += SEP;
        header += PROTOCOL;
        header += SEP;
        header += ":";
        // header = "REQUEST:";
        string local_time;
        if(get_local_time(local_time) == false)
        {
            _time.client_time = time(nullptr);  // 设置客户端时间
            message = to_string(_time.client_time) + ":" + message;
        }
        else
        {
            message = local_time + ":" + message;
        }
        return header + message;
    }

    string unwrap(const std::string& header) 
    {
        // cout << header.find(':') << endl;
        message = header.substr(header.find(':') + 1);
        size_t pos = message.find(':');
        if (pos != std::string::npos) {
            std::string client_time_str = message.substr(0, pos);
            _time.client_time = std::stoll(client_time_str);
            message = message.substr(pos + 1);
        }
        return message;
        // return header.substr(header.find(':') + 2, string::npos);
    }
    bool get_local_time(string& local_time)
    {
        ifstream file("time.txt"); // 打开文件
        string line;

        if (file.is_open()) 
        { // 检查文件是否成功打开
            while (getline(file, line)) 
            { // 从文件中逐行读取字符串到line中
                // std::cout<< line<< std::endl; // 输出读取到的字符串
            }
            file.close(); // 关闭文件
        } 
        else 
        {
            cout << "无法打开文件"<< endl;
            return false;
        }
        auto pos = line.find('-');
        if (pos != std::string::npos)
        {
            local_time = line.substr(0, pos);
            return true;
        }
        return false;
    }
public:
    std::string message;
    std::string header;
    TimeInfo _time;
};

class Response 
{
public:
    Response():message(""), header(""), _time({0, 0}) {}
    Response(const std::string& message) : message(message), _time({0, 0}) {}

    std::string wrap() 
    {
        header = "RESPONSE->";
        header += NTP_PORT;
        header += SEP;
        header += PROTOCOL;
        header += SEP;
        header += ":";
        _time.server_time = time(nullptr);  // 设置服务器时间
        message = std::to_string(_time.server_time) + ":" + message;
        return header + message;
        // header = "RESPONSE:" + message;
        // return header;
    }

    std::string unwrap(const std::string& header) 
    {
        message = header.substr(header.find(':') + 1);
        size_t pos = message.find(':');
        if (pos != std::string::npos) 
        {
            std::string server_time_str = message.substr(0, pos);
            _time.server_time = std::stoll(server_time_str);
            message = message.substr(pos + 1);
        }
        return message;
        // return header.substr(header.find(':'), string::npos);
    }
public:
    std::string message;
    std::string header;
    TimeInfo _time;
};